/**

 @Name：layui.layedit 富文本编辑器
 @Author：贤心
 @License：MIT

 */

layui.define(['layer', 'form'], function(exports){
	"use strict";

	var $ = layui.$
		,layer = layui.layer
		,form = layui.form
		,hint = layui.hint()
		,device = layui.device()

		,MOD_NAME = 'layedit', THIS = 'layui-this', SHOW = 'layui-show', ABLED = 'layui-disabled'

		,Edit = function(){
		var that = this;
		that.index = 0;

		//全局配置
		that.config = {
			//默认工具bar
			tool: [
				'strong', 'italic', 'underline', 'del'
				,'|'
				,'left', 'center', 'right'
				,'|'
				,'link', 'unlink', 'face', 'image'
			]
			,hideTool: []
			,height: 280 //默认高
		};
	};

	//全局设置
	Edit.prototype.set = function(options){
		var that = this;
		$.extend(true, that.config, options);
		return that;
	};

	//事件监听
	Edit.prototype.on = function(events, callback){
		return layui.onevent(MOD_NAME, events, callback);
	};

	//建立编辑器
	Edit.prototype.build = function(id, settings){
		settings = settings || {};

		var that = this
			,config = that.config
			,ELEM = 'layui-layedit', textArea = $(typeof(id)=='string'?'#'+id:id)
			,name =  'LAY_layedit_'+ (++that.index)
			,haveBuild = textArea.next('.'+ELEM)

			,set = $.extend({}, config, settings)

			,tool = function(){
			var node = [], hideTools = {};
			layui.each(set.hideTool, function(_, item){
				hideTools[item] = true;
			});
			layui.each(set.tool, function(_, item){
				if(tools[item] && !hideTools[item]){
					node.push(tools[item]);
				}
			});
			return node.join('');
		}()


			,editor = $(['<div class="'+ ELEM +'">'
			,'<div class="layui-unselect layui-layedit-tool">'+ tool +'</div>'
			,'<div class="layui-layedit-iframe">'
			,'<iframe id="'+ name +'" name="'+ name +'" textarea="'+ id +'" frameborder="0"></iframe>'
			,'</div>'
			,'</div>'].join(''))

		//编辑器不兼容ie8以下
		if(device.ie && device.ie < 8){
			return textArea.removeClass('layui-hide').addClass(SHOW);
		}

		haveBuild[0] && (haveBuild.remove());

		setIframe.call(that, editor, textArea[0], set)
		textArea.addClass('layui-hide').after(editor);

		return that.index;
	};

	//获得编辑器中内容
	Edit.prototype.getContent = function(index){
		var iframeWin = getWin(index);
		if(!iframeWin[0]) return;
		return toLower(iframeWin[0].document.body.innerHTML);
	};

	//获得编辑器中纯文本内容
	Edit.prototype.getText = function(index){
		var iframeWin = getWin(index);
		if(!iframeWin[0]) return;
		return $(iframeWin[0].document.body).text();
	};
	/**
	 * 设置编辑器内容
	 * @param {[type]} index   编辑器索引
	 * @param {[type]} content 要设置的内容
	 * @param {[type]} flag    是否追加模式
	 */
	Edit.prototype.setContent = function(index, content, flag){
		var iframeWin = getWin(index);
		if(!iframeWin[0]) return;
		if(flag){
			$(iframeWin[0].document.body).append(content)
		}else{
			$(iframeWin[0].document.body).html(content)
		};
		layedit.sync(index)
	};
	//将编辑器内容同步到textarea（一般用于异步提交时）
	Edit.prototype.sync = function(index){
		var iframeWin = getWin(index);
		if(!iframeWin[0]) return;
		var textarea = $('#'+iframeWin[1].attr('textarea'));
		textarea.val(toLower(iframeWin[0].document.body.innerHTML));
	};

	//获取编辑器选中内容
	Edit.prototype.getSelection = function(index){
		var iframeWin = getWin(index);
		if(!iframeWin[0]) return;
		var range = Range(iframeWin[0].document);
		return document.selection ? range.text : range.toString();
	};

	//iframe初始化
	var setIframe = function(editor, textArea, set){
			var that = this, iframe = editor.find('iframe');

			iframe.css({
				height: set.height
			}).on('load', function(){
				var conts = iframe.contents()
					,iframeWin = iframe.prop('contentWindow')
					,head = conts.find('head')
					,style = $(['<style>'
					,'*{margin: 0; padding: 0;}'
					,'body{padding: 10px; line-height: 20px; overflow-x: hidden; word-wrap: break-word; font: 14px Helvetica Neue,Helvetica,PingFang SC,Microsoft YaHei,Tahoma,Arial,sans-serif; -webkit-box-sizing: border-box !important; -moz-box-sizing: border-box !important; box-sizing: border-box !important;}'
					,'a{color:#01AAED; text-decoration:none;}a:hover{color:#c00}'
					,'p{margin-bottom: 10px;}'
					,'img{display: inline-block; border: none; vertical-align: middle;}'
					,'pre{margin: 10px 0; padding: 10px; line-height: 20px; border: 1px solid #ddd; border-left-width: 6px; background-color: #F2F2F2; color: #333; font-family: Courier New; font-size: 12px;}'
					,'</style>'].join(''))
					,body = conts.find('body');

				head.append(style);
				body.attr('contenteditable', 'true').css({
					'min-height': set.height
				}).html(textArea.value||'');

				hotkey.apply(that, [iframeWin, iframe, textArea, set]); //快捷键处理
				toolActive.call(that, iframeWin, editor, set); //触发工具

			});
		}

		//获得iframe窗口对象
		,getWin = function(index){
			var iframe = $('#LAY_layedit_'+ index)
				,iframeWin = iframe.prop('contentWindow');
			return [iframeWin, iframe];
		}

		//IE8下将标签处理成小写
		,toLower = function(html){
			if(device.ie == 8){
				html = html.replace(/<.+>/g, function(str){
					return str.toLowerCase();
				});
			}
			return html;
		}

		//快捷键处理
		,hotkey = function(iframeWin, iframe, textArea, set){
			var iframeDOM = iframeWin.document, body = $(iframeDOM.body);
			body.on('keydown', function(e){
				var keycode = e.keyCode;
				//处理回车
				if(keycode === 13){
					var range = Range(iframeDOM);
					var container = getContainer(range)
						,parentNode = container.parentNode;

					if(parentNode.tagName.toLowerCase() === 'pre'){
						if(e.shiftKey) return
						layer.msg('请暂时用shift+enter');
						return false;
					}
					iframeDOM.execCommand('formatBlock', false, '<p>');
				}
			});

			//给textarea同步内容
			$(textArea).parents('form').on('submit', function(){
				var html = body.html();
				//IE8下将标签处理成小写
				if(device.ie == 8){
					html = html.replace(/<.+>/g, function(str){
						return str.toLowerCase();
					});
				}
				textArea.value = html;
			});

			//处理粘贴
			body.on('paste', function(e){
				iframeDOM.execCommand('formatBlock', false, '<p>');
				setTimeout(function(){
					filter.call(iframeWin, body);
					textArea.value = body.html();
				}, 100);
			});
		}

		//标签过滤
		,filter = function(body){
			var iframeWin = this
				,iframeDOM = iframeWin.document;

			//清除影响版面的css属性
			body.find('*[style]').each(function(){
				var textAlign = this.style.textAlign;
				this.removeAttribute('style');
				$(this).css({
					'text-align': textAlign || ''
				})
			});

			//修饰表格
			body.find('table').addClass('layui-table');

			//移除不安全的标签
			body.find('script,link').remove();
		}

		//Range对象兼容性处理
		,Range = function(iframeDOM){
			return iframeDOM.selection
				? iframeDOM.selection.createRange()
				: iframeDOM.getSelection().getRangeAt(0);
		}

		//当前Range对象的endContainer兼容性处理
		,getContainer = function(range){
			return range.endContainer || range.parentElement().childNodes[0]
		}

		//在选区插入内联元素
		,insertInline = function(tagName, attr, range){
			var iframeDOM = this.document
				,elem = document.createElement(tagName)
			for(var key in attr){
				elem.setAttribute(key, attr[key]);
			}
			elem.removeAttribute('text');

			if(iframeDOM.selection){ //IE
				var text = range.text || attr.text;
				if(tagName === 'a' && !text) return;
				if(text){
					elem.innerHTML = text;
				}
				range.pasteHTML($(elem).prop('outerHTML'));
				range.select();
			} else { //非IE
				var text = range.toString() || attr.text;
				if(tagName === 'a' && !text) return;
				if(text){
					elem.innerHTML = text;
				}
				range.deleteContents();
				range.insertNode(elem);
			}
		}

		//工具选中
		,toolCheck = function(tools, othis){
			var iframeDOM = this.document
				,CHECK = 'layedit-tool-active'
				,container = getContainer(Range(iframeDOM))
				,item = function(type){
				return tools.find('.layedit-tool-'+type)
			}

			if(othis){
				othis[othis.hasClass(CHECK) ? 'removeClass' : 'addClass'](CHECK);
			}

			tools.find('>i').removeClass(CHECK);
			item('unlink').addClass(ABLED);

			$(container).parents().each(function(){
				var tagName = this.tagName.toLowerCase()
					,textAlign = this.style.textAlign;

				//文字
				if(tagName === 'b' || tagName === 'strong'){
					item('b').addClass(CHECK)
				}
				if(tagName === 'i' || tagName === 'em'){
					item('i').addClass(CHECK)
				}
				if(tagName === 'u'){
					item('u').addClass(CHECK)
				}
				if(tagName === 'strike'){
					item('d').addClass(CHECK)
				}

				//对齐
				if(tagName === 'p'){
					if(textAlign === 'center'){
						item('center').addClass(CHECK);
					} else if(textAlign === 'right'){
						item('right').addClass(CHECK);
					} else {
						item('left').addClass(CHECK);
					}
				}

				//超链接
				if(tagName === 'a'){
					item('link').addClass(CHECK);
					item('unlink').removeClass(ABLED);
				}
			});
		}

		//触发工具
		,toolActive = function(iframeWin, editor, set){
			var iframeDOM = iframeWin.document
				,body = $(iframeDOM.body)
				,toolEvent = {
				//超链接
				link: function(range){
					var container = getContainer(range)
						,parentNode = $(container).parent();

					link.call(body, {
						href: parentNode.attr('href')
						,target: parentNode.attr('target')
					}, function(field){
						var parent = parentNode[0];
						if(parent.tagName === 'A'){
							parent.href = field.url;
						} else {
							insertInline.call(iframeWin, 'a', {
								target: field.target
								,href: field.url
								,text: field.url
							}, range);
						}
					});
				}
				//清除超链接
				,unlink: function(range){
					iframeDOM.execCommand('unlink');
				}
				//表情
				,face: function(range){
					face.call(this, function(img){
						insertInline.call(iframeWin, 'img', {
							src: img.src
							,alt: img.alt
						}, range);
					});
				}
				//图片
				,image: function(range){
					var that = this;
					layui.use('upload', function(upload){
						var uploadImage = set.uploadImage || {};
						upload.render({
							url: uploadImage.url
							,method: uploadImage.type
							,elem: $(that).find('input')[0]
							,done: function(res){
								console.log(res);
								if(res.code == "000"){
									insertInline.call(iframeWin, 'img', {
										src: res.item.url
										,alt: res.item.title
									}, range);
								} else {
									layer.msg(res.msg||'上传失败');
								}
							}
						});
					});
				}
				//插入代码
				,code: function(range){
					code.call(body, function(pre){
						insertInline.call(iframeWin, 'pre', {
							text: pre.code
							,'lay-lang': pre.lang
						}, range);
					});
				}
				//帮助
				,help: function(){
					layer.open({
						type: 2
						,title: '帮助'
						,area: ['600px', '380px']
						,shadeClose: true
						,shade: 0.1
						,skin: 'layui-layer-msg'
						,content: ['http://www.layui.com/about/layedit/help.html', 'no']
					});
				}
			}
				,tools = editor.find('.layui-layedit-tool')

				,click = function(){
				var othis = $(this)
					,events = othis.attr('layedit-event')
					,command = othis.attr('lay-command');

				if(othis.hasClass(ABLED)) return;

				body.focus();

				var range = Range(iframeDOM)
					,container = range.commonAncestorContainer

				if(command){
					iframeDOM.execCommand(command);
					if(/justifyLeft|justifyCenter|justifyRight/.test(command)){
						iframeDOM.execCommand('formatBlock', false, '<p>');
					}
					setTimeout(function(){
						body.focus();
					}, 10);
				} else {
					toolEvent[events] && toolEvent[events].call(this, range);
				}
				toolCheck.call(iframeWin, tools, othis);
			}

				,isClick = /image/

			tools.find('>i').on('mousedown', function(){
				var othis = $(this)
					,events = othis.attr('layedit-event');
				if(isClick.test(events)) return;
				click.call(this)
			}).on('click', function(){
				var othis = $(this)
					,events = othis.attr('layedit-event');
				if(!isClick.test(events)) return;
				click.call(this)
			});

			//触发内容区域
			body.on('click', function(){
				toolCheck.call(iframeWin, tools);
				layer.close(face.index);
			});
		}

		//超链接面板
		,link = function(options, callback){
			var body = this, index = layer.open({
				type: 1
				,id: 'LAY_layedit_link'
				,area: '350px'
				,shade: 0.05
				,shadeClose: true
				,moveType: 1
				,title: '超链接'
				,skin: 'layui-layer-msg'
				,content: ['<ul class="layui-form" style="margin: 15px;">'
					,'<li class="layui-form-item">'
					,'<label class="layui-form-label" style="width: 60px;">URL</label>'
					,'<div class="layui-input-block" style="margin-left: 90px">'
					,'<input name="url" lay-verify="url" value="'+ (options.href||'') +'" autofocus="true" autocomplete="off" class="layui-input">'
					,'</div>'
					,'</li>'
					,'<li class="layui-form-item">'
					,'<label class="layui-form-label" style="width: 60px;">打开方式</label>'
					,'<div class="layui-input-block" style="margin-left: 90px">'
					,'<input type="radio" name="target" value="_self" class="layui-input" title="当前窗口"'
					+ ((options.target==='_self' || !options.target) ? 'checked' : '') +'>'
					,'<input type="radio" name="target" value="_blank" class="layui-input" title="新窗口" '
					+ (options.target==='_blank' ? 'checked' : '') +'>'
					,'</div>'
					,'</li>'
					,'<li class="layui-form-item" style="text-align: center;">'
					,'<button type="button" lay-submit lay-filter="layedit-link-yes" class="layui-btn"> 确定 </button>'
					,'<button style="margin-left: 20px;" type="button" class="layui-btn layui-btn-primary"> 取消 </button>'
					,'</li>'
					,'</ul>'].join('')
				,success: function(layero, index){
					var eventFilter = 'submit(layedit-link-yes)';
					form.render('radio');
					layero.find('.layui-btn-primary').on('click', function(){
						layer.close(index);
						body.focus();
					});
					form.on(eventFilter, function(data){
						layer.close(link.index);
						callback && callback(data.field);
					});
				}
			});
			link.index = index;
		}

		//表情面板
		,face = function(callback){
			//表情库
			var faces = function(){
				var alt = ["[微笑]", "[嘻嘻]", "[哈哈]", "[可爱]", "[可怜]", "[挖鼻]", "[吃惊]", "[害羞]", "[挤眼]", "[闭嘴]", "[鄙视]", "[爱你]", "[泪]", "[偷笑]", "[亲亲]", "[生病]", "[太开心]", "[白眼]", "[右哼哼]", "[左哼哼]", "[嘘]", "[衰]", "[委屈]", "[吐]", "[哈欠]", "[抱抱]", "[怒]", "[疑问]", "[馋嘴]", "[拜拜]", "[思考]", "[汗]", "[困]", "[睡]", "[钱]", "[失望]", "[酷]", "[色]", "[哼]", "[鼓掌]", "[晕]", "[悲伤]", "[抓狂]", "[黑线]", "[阴险]", "[怒骂]", "[互粉]", "[心]", "[伤心]", "[猪头]", "[熊猫]", "[兔子]", "[ok]", "[耶]", "[good]", "[NO]", "[赞]", "[来]", "[弱]", "[草泥马]", "[神马]", "[囧]", "[浮云]", "[给力]", "[围观]", "[威武]", "[奥特曼]", "[礼物]", "[钟]", "[话筒]", "[蜡烛]", "[蛋糕]"], arr = {};
				layui.each(alt, function(index, item){
					arr[item] = layui.cache.dir + 'images/face/'+ index + '.gif';
				});
				return arr;
			}();
			face.hide = face.hide || function(e){
				if($(e.target).attr('layedit-event') !== 'face'){
					layer.close(face.index);
				}
			}
			return face.index = layer.tips(function(){
				var content = [];
				layui.each(faces, function(key, item){
					content.push('<li title="'+ key +'"><img src="'+ item +'" alt="'+ key +'"></li>');
				});
				return '<ul class="layui-clear">' + content.join('') + '</ul>';
			}(), this, {
				tips: 1
				,time: 0
				,skin: 'layui-box layui-util-face'
				,maxWidth: 500
				,success: function(layero, index){
					layero.css({
						marginTop: -4
						,marginLeft: -10
					}).find('.layui-clear>li').on('click', function(){
						callback && callback({
							src: faces[this.title]
							,alt: this.title
						});
						layer.close(index);
					});
					$(document).off('click', face.hide).on('click', face.hide);
				}
			});
		}

		//插入代码面板
		,code = function(callback){
			var body = this, index = layer.open({
				type: 1
				,id: 'LAY_layedit_code'
				,area: '550px'
				,shade: 0.05
				,shadeClose: true
				,moveType: 1
				,title: '插入代码'
				,skin: 'layui-layer-msg'
				,content: ['<ul class="layui-form layui-form-pane" style="margin: 15px;">'
					,'<li class="layui-form-item">'
					,'<label class="layui-form-label">请选择语言</label>'
					,'<div class="layui-input-block">'
					,'<select name="lang">'
					,'<option value="JavaScript">JavaScript</option>'
					,'<option value="HTML">HTML</option>'
					,'<option value="CSS">CSS</option>'
					,'<option value="Java">Java</option>'
					,'<option value="PHP">PHP</option>'
					,'<option value="C#">C#</option>'
					,'<option value="Python">Python</option>'
					,'<option value="Ruby">Ruby</option>'
					,'<option value="Go">Go</option>'
					,'</select>'
					,'</div>'
					,'</li>'
					,'<li class="layui-form-item layui-form-text">'
					,'<label class="layui-form-label">代码</label>'
					,'<div class="layui-input-block">'
					,'<textarea name="code" lay-verify="required" autofocus="true" class="layui-textarea" style="height: 200px;"></textarea>'
					,'</div>'
					,'</li>'
					,'<li class="layui-form-item" style="text-align: center;">'
					,'<button type="button" lay-submit lay-filter="layedit-code-yes" class="layui-btn"> 确定 </button>'
					,'<button style="margin-left: 20px;" type="button" class="layui-btn layui-btn-primary"> 取消 </button>'
					,'</li>'
					,'</ul>'].join('')
				,success: function(layero, index){
					var eventFilter = 'submit(layedit-code-yes)';
					form.render('select');
					layero.find('.layui-btn-primary').on('click', function(){
						layer.close(index);
						body.focus();
					});
					form.on(eventFilter, function(data){
						layer.close(code.index);
						callback && callback(data.field);
					});
				}
			});
			code.index = index;
		}

		//全部工具
		,tools = {
			html: '<i class="layui-icon layedit-tool-html" title="HTML源代码" lay-command="html" layedit-event="html"">&#xe64b;</i><span class="layedit-tool-mid"></span>'
			,strong: '<i class="layui-icon layedit-tool-b" title="加粗" lay-command="Bold" layedit-event="b"">&#xe62b;</i>'
			,italic: '<i class="layui-icon layedit-tool-i" title="斜体" lay-command="italic" layedit-event="i"">&#xe644;</i>'
			,underline: '<i class="layui-icon layedit-tool-u" title="下划线" lay-command="underline" layedit-event="u"">&#xe646;</i>'
			,del: '<i class="layui-icon layedit-tool-d" title="删除线" lay-command="strikeThrough" layedit-event="d"">&#xe64f;</i>'

			,'|': '<span class="layedit-tool-mid"></span>'

			,left: '<i class="layui-icon layedit-tool-left" title="左对齐" lay-command="justifyLeft" layedit-event="left"">&#xe649;</i>'
			,center: '<i class="layui-icon layedit-tool-center" title="居中对齐" lay-command="justifyCenter" layedit-event="center"">&#xe647;</i>'
			,right: '<i class="layui-icon layedit-tool-right" title="右对齐" lay-command="justifyRight" layedit-event="right"">&#xe648;</i>'
			,link: '<i class="layui-icon layedit-tool-link" title="插入链接" layedit-event="link"">&#xe64c;</i>'
			,unlink: '<i class="layui-icon layedit-tool-unlink layui-disabled" title="清除链接" lay-command="unlink" layedit-event="unlink"">&#xe64d;</i>'
			,face: '<i class="layui-icon layedit-tool-face" title="表情" layedit-event="face"">&#xe650;</i>'
			,image: '<i class="layui-icon layedit-tool-image" title="图片" layedit-event="image">&#xe64a;<input type="file" name="file"></i>'
			,code: '<i class="layui-icon layedit-tool-code" title="插入代码" layedit-event="code">&#xe64e;</i>'

			,help: '<i class="layui-icon layedit-tool-help" title="帮助" layedit-event="help">&#xe607;</i>'
		}

		,edit = new Edit();

	exports(MOD_NAME, edit);
});
